﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using RuoVea.ExConfig;
using RuoVea.ExJwtBearer;
using RuoVea.ExPws;
using RuoVea.ExPws.Options;
using RuoVea.ExSugar;
using RuoVea.OmiApi.Auth.Entitys;
using RuoVea.OmiApi.Auth.SeedData;
using RuoVea.OmiApi.Auth.Service;
using RuoVea.OmiApi.Config;
using SqlSugar;

namespace RuoVea.OmiApi.Auth
{
    /// <summary>
    /// 注入扩展
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 用户登陆
        /// </summary>
        /// <param name="services"></param>
        /// <param name="serviceLifetime">Scoped</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static IServiceCollection AddOmiAuthSetup(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            services.Configure<DbInitConfig>(AppSettings.Configuration.GetSection("DbInitConfig"));
            return DI(services, null, serviceLifetime);
        }

        /// <summary>
        /// 用户登陆
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <param name="serviceLifetime">Scoped</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static IServiceCollection AddOmiAuthSetup(this IServiceCollection services, IConfiguration config,  ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (config == null) throw new ArgumentNullException(nameof(config));
            services.Configure<DbInitConfig>(config);
            DbInitConfig dbInitConfig = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
            return DI(services, dbInitConfig, serviceLifetime);
        }

        /// <summary>
        /// 用户登陆
        /// </summary>
        /// <param name="services"></param>
        /// <param name="config"></param>
        /// <param name="serviceLifetime">Scoped</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static IServiceCollection AddOmiAuthSetup(this IServiceCollection services, Action<DbInitConfig> config,  ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (config == null) throw new ArgumentNullException(nameof(config));
            services.Configure(config);
            DbInitConfig dbInitConfig = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
            return DI(services, dbInitConfig, serviceLifetime);
        }

        #region DI
        private static IServiceCollection DI(IServiceCollection services, DbInitConfig dbInitConfig, ServiceLifetime serviceLifetime)
        {
            services.AddJwtSetup();
            
            services.Configure<PasswordConfig>(AppSettings.Configuration.GetSection("PasswordConfig"));

            services.AddCaptcha(AppSettings.Configuration);

            switch (serviceLifetime)
            {
                case ServiceLifetime.Scoped:
                    services.AddScoped<ICurrentUserManager>();
                    services.AddScoped<IPasswordServer>();
                    services.AddScoped<AuthService>();
                    break;
                case ServiceLifetime.Singleton:
                    services.AddSingleton<ICurrentUserManager>();
                    services.AddSingleton<IPasswordServer>();
                    services.AddSingleton<AuthService>();
                    break;
                case ServiceLifetime.Transient:
                    services.AddTransient<ICurrentUserManager>();
                    services.AddTransient<IPasswordServer>();
                    services.AddTransient<AuthService>();
                    break;
            }
            services.AddOmiConfigSetup((o) => { o = dbInitConfig; }, serviceLifetime);
            return services;
        }
        #endregion

        /// <summary>
        /// 用户登陆 - 初始化数据库/初始化种子数据
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddAuthInitSetup(this IServiceCollection services)
        {
            services.AddConfigInitSetup();
            DbInitConfig config = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
            var _thisRepository = services.BuildServiceProvider().GetRequiredService<ISqlSugarClient>();

            PasswordConfig passwordConfig = services.BuildServiceProvider().GetRequiredService<IOptions<PasswordConfig>>()?.Value;
            IPasswordServer passwordServer = services.BuildServiceProvider().GetRequiredService<IPasswordServer>();

            Task.Run(() =>
            {
                if (config.InitTable && _thisRepository != null)
                {
                    if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysUser), false) || _thisRepository.DbMaintenance.IsAnyTable("sys_user", false)) { }
                    else
                    {
                        _thisRepository.CodeFirst.InitTables<SysUser>();
                        if (config.InitSeedData)
                        {
                            var seedData = new SysUserSeedData().HasData().ToList();
                            string defaultEncryptPassword = passwordServer.Encrypt(passwordConfig.DefaultPassword);
                            seedData.ForEach(x => x.Password = defaultEncryptPassword);
                            _thisRepository.Storageable(seedData).ToStorage().AsInsertable.ExecuteCommand();
                        }
                    }
                }
            });
            return services;
        }
    }
}
